import cv2 as cv 
import numpy as np
import copy
from matplotlib import pyplot as plt 
fl = '/Users/cuidiedie/Desktop/python/'
fileName = fl+'lena.png'
###作业1
img = cv.imread(fileName)
# source = cv.cvtColor(img,cv.COLOR_BGR2RGB)
#均值滤波
blur = cv.blur(img,(5,5))
#高斯模糊
gauss = cv.GaussianBlur(img,(5,5),0.5)
#中值滤波
median = cv.medianBlur(img,5)
# cv.imshow('img',img)
# cv.imshow('Blur',blur)
# cv.imshow('gauss',gauss)
# cv.imshow('median',median)
###作业2
#边缘检测
#转化灰度图
imggray =  cv.imread(fileName,0)
#利用sobel方法可以进行sobel边缘检测 CV_64F表示64位浮点数即64float，这里不适用nupy。float64因为可能会溢出
#第三第四参数是在x，y方向求导0，表示不求导，1表示求偏导，（差分）2表示求二次导

sobel = cv.Sobel(imggray,cv.CV_16S,1,1,ksize=5)

x = cv.Sobel(imggray,cv.CV_64F,1,0)  #1,0代表只计算x方向计算边缘
y = cv.Sobel(imggray,cv.CV_64F,0,1)  #0,1代表只在y方向计算边缘
absX = cv.convertScaleAbs(x)#像素取绝对值
absY = cv.convertScaleAbs(y)
dst = cv.addWeighted(absX,0.5,absY,0.5,0)
# sobel2 = cv.Sobel(imggray,cv.CV_64F,2,2,ksize=5)
canny = cv.Canny(imggray,100,150)
# 当阈值大的时候，检测的边缘少；当阈值小的时候，检测的边缘多而杂；具体两个阈值选多少，还是要看具体情况而定
# cv.imshow('imgg',imggray)
# cv.imshow('sobel',dst)
# cv.imshow('sobelx',sobelx)
# cv.imshow('sobely',sobely)
# cv.imshow('sobel2',sobel2)
# cv.imshow('canny',canny)

#作业3
fileName1 = fl+'pic2.png'#噪声图
fileName2 = fl+'pic6.png'#渐变图

#gray
im1 = cv.imread(fileName1)
im2 = cv.imread(fileName2)

gray1 = cv.cvtColor(im1,cv.COLOR_BGR2GRAY)
gray2 = cv.cvtColor(im2,cv.COLOR_BGR2GRAY)
# hist = cv.calcHist([im1],[0],None,[256],[0,255])
reveal,dst = cv.threshold(gray1,0,255,cv.THRESH_OTSU)

reveal2,dst2 = cv.threshold(gray2,0,255,cv.THRESH_OTSU)
# #噪声图
# cv.imshow('gray1',gray1)
# plt.hist(gray1.ravel(),256)
cv.imshow('dst',dst)
# plt.hist(gray1.ravel(),256)
cv.imshow('dst2',dst2)
# plt.hist(gray2.ravel(),256)
# plt.show()

fileRice = fl+'rice.png'

###计算3sigm内的米粒
imr = cv.imread(fileRice,0)
element = cv.getStructuringElement(cv.MORPH_RECT,(3,3))
bw = cv.morphologyEx(imr,cv.MORPH_OPEN,element)
_,bw=cv.threshold(bw,0,0xff,cv.THRESH_OTSU)
seg = copy.deepcopy(bw)
bin,cnts,hire = cv.findContours(seg,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
count = 0

for i in range (len(cnts),0,-1):
    c = cnts[i-1]
    area = cv.contourArea(c)

    if area < 10 :
        continue
    count = count + 1

    x,y,w,h = cv.boundingRect(c)

    cv.rectangle(imr,(x,y),(x+w,y+h),(0,0,0xff),1)

    cv.putText(imr,str(count),(x,y),cv.FONT_HERSHEY_PLAIN,0.5,(0,0xff,0))
print(count)
# cv.imshow('rice',imr)

####角点检测
jd1 = fl + 'butterfly.jpg'
jd2 = fl + 'chessboard.png'

jdim1 = cv.imread(jd1,0)

jdim2 = cv.imread(jd2,0)
sift = cv.xfeatures2d.SIFT_create()

kp1 = sift.detect(jdim1,None)
kp2 = sift.detect(jdim2,None)

image_1 = cv.drawKeypoints(jdim1,kp1,jdim1)
image_2 = cv.drawKeypoints(jdim2,kp2,jdim2)


orb = cv.ORB_create()
kp_1 = orb.detect(jdim1,None)
kp_2 = orb.detect(jdim2,None)

image_3 = cv.drawKeypoints(jdim1,kp_1,jdim1)
image_4 = cv.drawKeypoints(jdim2,kp_2,jdim2,)

###FAST

fast = cv.FastFeatureDetector_create()

kpf = fast.detect(jdim1,None)


image_5 = cv.drawKeypoints(jdim1,kpf,jdim1)


#har
dstH = cv.cornerHarris(jdim2,2,3,0.04)
dstH = cv.dilate(dstH,None)
image_2[dstH>0.01*dstH.max()] = [0,0,255]#dstH>0.01*dstH.max()这么多返回是满足条件的dst索引值　　根据索引值来设置这个点的颜色
# cv.imshow('harris',jdim2)
cv.imwrite(fl+'harris.png',image_2)
# cv.imshow('jd1.png',image_1)
# cv.imshow('jd3.png',image_3)
# cv.imshow('jd5.png',image_5)

cv.waitKey(0)

cv.destroyAllWindows()